﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.UI;
using Xpedite.Config;
using Xpedite.Extensions;
using Xpedite.Localization;
using Xpedite.Resources;
using Xpedite.WebAbstraction;

/* Copyright (c) 2010 CBaxter
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
 * IN THE SOFTWARE. 
 */

namespace Xpedite.WebControls
{
  [
  PersistChildren(false),
  DefaultProperty("Resources"),
  ParseChildren(true, "Resources"),
  ToolboxData("<{0}:CompositeResource runat=\"server\" Type=\"Unknown\"></{0}:CompositeResource>"),
  Designer("System.Web.UI.Design.WebControls.PreviewControlDesigner, System.Design, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
  ]
  public class CompositeResource : Control
  {
    private static readonly Regex DefaultNameRegex = new Regex(@"^[a-zA-Z]+[_a-zA-Z0-9-\.]*$", RegexOptions.Singleline);
    private static readonly Regex CssNameRegex = new Regex(@"^[a-zA-Z]+[_a-zA-Z0-9-]*$", RegexOptions.Singleline);

    private readonly ResourceCollection _resources = new ResourceCollection();
    private readonly ConfigMode _mode = ConfigSectionHandler.Instance.Mode;

    [Bindable(true), DefaultValue(ResourceType.Unknown), Description("Specifies the ResourceType of the CompositeControl (i.e., Css, JavaScript, Png etc).")]
    public ResourceType Type { get; set; }

    [Bindable(true), DefaultValue(""), Description("Specifies the reference name of the CompositeControl. The ReferenceName is typically used in conjunction with the Sprite control.")]
    public String ReferenceName { get; set; }

    [Bindable(true), DefaultValue(""), Description("Specifies whether or not the composite resource definition can be extended (i.e., partial definition).")]
    public Boolean Extendable { get; set; }

    [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    public ResourceCollection Resources { get { return _resources; } }

    protected override void OnPreRender(EventArgs e)
    {
      base.OnPreRender(e);

      if (Resources.Count == 0)
        return;

      var webPage = new WebPage(Page);
      var referenceName = String.IsNullOrEmpty(ReferenceName) ? Path.GetFileNameWithoutExtension(Page.Request.Url.AbsolutePath) : ReferenceName;

      if (Extendable)
        webPage.GetResourceContext().CreateOrExtendResourceDefinition(Type, referenceName, GetNamedResources(webPage, referenceName));
      else
        webPage.GetResourceContext().CreateResourceDefinition(Type, referenceName, GetNamedResources(webPage, referenceName));
    }

    internal IEnumerable<INamedValue<IResourceUrl>> GetNamedResources(IWebPage webPage, String defintion)
    {
      return Resources.Select((resource) => NamedValue.Create(GetOrCreateResourceReferenceName(resource), (IResourceUrl)new ResourceUrl(webPage.Request, ResolveUrl(resource.Url))));
    }

    private String GetOrCreateResourceReferenceName(Resource resource)
    {
      return String.IsNullOrEmpty(resource.ReferenceName)
             ? "resource-" + (resource.Url ?? String.Empty).GetHexHashCode()
             : resource.ReferenceName;
    }
  }
}
